home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
ici
/
ici.cpi
/
call.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-27
|
5KB
|
218 lines
#include "buf.h"
#include "exec.h"
#include "func.h"
#include "int.h"
#include "float.h"
#include "str.h"
#include "null.h"
#include "op.h"
#include "catch.h"
#include <stdarg.h>
/*
* The common code used by ici_func() and ici_call() below.
*/
static char *
call(object_t *func_obj, char *types, va_list va)
{
object_t *call_obj;
catch_t *frame;
int nargs;
int arg;
object_t *ret_obj;
char ret_type;
char *ret_ptr;
int os_depth;
if (types[0] != '\0' && types[1] == '=')
{
ret_type = types[0];
ret_ptr = va_arg(va, char *);
types += 2;
}
else
{
ret_type = '\0';
ret_ptr = NULL;
}
os_depth = o_top - os->a_base;
call_obj = NULL;
/*
* We include an extra 80 in our pushcheck, see start of evaluate().
*/
nargs = strlen(types);
if (pushcheck(os, nargs + 80))
return error;
for (arg = 0; arg < nargs; ++arg)
*o_top++ = objof(&o_null);
for (arg = -1; arg >= -nargs; --arg)
{
switch (*types++)
{
case 'o':
o_top[arg] = va_arg(va, object_t *);
break;
case 'i':
if ((o_top[arg] = objof(new_int(va_arg(va, long)))) == NULL)
goto fail;
loose(o_top[arg]);
break;
case 'q':
o_top[arg] = objof(&o_quote);
--nargs;
break;
case 's':
if ((o_top[arg] = objof(new_cname(va_arg(va, char *)))) == NULL)
goto fail;
loose(o_top[arg]);
break;
case 'f':
if ((o_top[arg] = objof(new_float(va_arg(va, double)))) == NULL)
goto fail;
loose(o_top[arg]);
break;
default:
error = "error in function call";
goto fail;
}
}
*o_top++ = func_obj;
if ((call_obj = objof(new_op(NULL, OP_CALL, nargs))) == NULL)
goto fail;
if ((frame = new_catch(NULL, os_depth, v_top - vs->a_base)) == NULL)
goto fail;
if ((ret_obj = ici_evaluate(objof(call_obj), frame)) == NULL)
goto fail;
switch (ret_type)
{
case '\0':
loose(ret_obj);
break;
case 'o':
*(object_t **)ret_ptr = ret_obj;
break;
case 'i':
if (!isint(ret_obj))
goto typeclash;
*(long *)ret_ptr = intof(ret_obj)->i_value;
loose(ret_obj);
break;
case 'f':
if (!isfloat(ret_obj))
goto typeclash;
*(double *)ret_ptr = floatof(ret_obj)->f_value;
loose(ret_obj);
break;
case 's':
if (!isstring(ret_obj))
goto typeclash;
*(char **)ret_ptr = stringof(ret_obj)->s_chars;
loose(ret_obj);
break;
default:
typeclash:
loose(ret_obj);
error = "incorrect return type";
goto fail;
}
loose(call_obj);
return NULL;
fail:
if (call_obj != NULL)
loose(call_obj);
o_top = os->a_base + os_depth;
return error;
}
/*
* ici_func(func, types, args...)
*
* Call an ICI function from C with simple argument types and return value.
*
* Types can be of the forms ".=..." or "...". In the first case the 1st
* extra arg is used as a pointer to store the return value through.
*
* Type key letters are:
* i a long
* f a double
* s a '\0' terminated string
* o an ici object
*
* When a string is returned it is a pointer to the character data of an
* internal ICI string object. It will only remain valid until the next
* call to any ICI function. When an object is returned it is not loose
* (i.e. it is held against garbage collection).
*/
char *
ici_func(object_t *func_obj, char *types, ...)
{
va_list va;
char *result;
va_start(va, types);
result = call(func_obj, types, va);
va_end(va);
return result;
}
/*
* ici_call(name, types, args...)
*
* Call an ici function by name from C with simple argument types and
* return value. The named is looked up in the current scope.
*
* Types can be of the forms ".=..." or "...". In the first case the 1st
* extra arg is used as a pointer to store the return value through.
*
* Type key letters are:
* i a long
* f a double
* s a '\0' terminated string
* o an ici object
*
* When a string is returned it is a pointer to the character data of an
* internal ICI string object. It will only remain valid until the next
* call to any ICI function. When an object is returned it is not loose
* (i.e. it is held against garbage collection).
*/
char *
ici_call(char *func_name, char *types, ...)
{
object_t *name_obj;
object_t *func_obj;
va_list va;
char *result;
name_obj = NULL;
func_obj = NULL;
va_start(va, types);
if ((name_obj = objof(new_cname(func_name))) == NULL)
return error;
if ((func_obj = fetch(v_top[-1], name_obj)) == objof(&o_null))
{
sprintf(buf, "\"%s\" undefined", func_name);
error = buf;
loose(name_obj);
return error;
}
loose(name_obj);
name_obj = NULL;
result = call(func_obj, types, va);
loose(func_obj);
va_end(va);
return result;
}